
const _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault');

exports.__esModule = true;
exports.default = void 0;

const _date = require('../utils/validate/date');

const _scroll = require('../utils/dom/scroll');

const _utils = require('./utils');

const _popup = _interopRequireDefault(require('../popup'));

const _button = _interopRequireDefault(require('../button'));

const _toast = _interopRequireDefault(require('../toast'));

const _Month = _interopRequireDefault(require('./components/Month'));

const _Header = _interopRequireDefault(require('./components/Header'));

// Utils
// Components
const _default2 = (0, _utils.createComponent)({
  props: {
    title: String,
    color: String,
    value: Boolean,
    formatter: Function,
    confirmText: String,
    rangePrompt: String,
    defaultDate: [Date, Array],
    getContainer: [String, Function],
    allowSameDay: Boolean,
    closeOnPopstate: Boolean,
    confirmDisabledText: String,
    type: {
      type: String,
      default: 'single',
    },
    minDate: {
      type: Date,
      validator: _date.isDate,
      default: function _default() {
        return new Date();
      },
    },
    maxDate: {
      type: Date,
      validator: _date.isDate,
      default: function _default() {
        const now = new Date();
        return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate());
      },
    },
    position: {
      type: String,
      default: 'bottom',
    },
    rowHeight: {
      type: [Number, String],
      default: _utils.ROW_HEIGHT,
    },
    round: {
      type: Boolean,
      default: true,
    },
    poppable: {
      type: Boolean,
      default: true,
    },
    showMark: {
      type: Boolean,
      default: true,
    },
    showTitle: {
      type: Boolean,
      default: true,
    },
    showConfirm: {
      type: Boolean,
      default: true,
    },
    showSubtitle: {
      type: Boolean,
      default: true,
    },
    safeAreaInsetBottom: {
      type: Boolean,
      default: true,
    },
    closeOnClickOverlay: {
      type: Boolean,
      default: true,
    },
    maxRange: {
      type: [Number, String],
      default: null,
    },
  },
  data: function data() {
    return {
      subtitle: '',
      currentDate: this.getInitialDate(),
    };
  },
  computed: {
    months: function months() {
      const months = [];
      const cursor = new Date(this.minDate);
      cursor.setDate(1);

      do {
        months.push(new Date(cursor));
        cursor.setMonth(cursor.getMonth() + 1);
      } while ((0, _utils.compareMonth)(cursor, this.maxDate) !== 1);

      return months;
    },
    buttonDisabled: function buttonDisabled() {
      const { type } = this;
      const { currentDate } = this;

      if (type === 'range') {
        return !currentDate[0] || !currentDate[1];
      }

      if (type === 'multiple') {
        return !currentDate.length;
      }

      return !currentDate;
    },
  },
  watch: {
    type: 'reset',
    value: 'init',
    defaultDate: function defaultDate(val) {
      this.currentDate = val;
      this.scrollIntoView();
    },
  },
  mounted: function mounted() {
    this.init();
  },

  /* istanbul ignore next */
  activated: function activated() {
    this.init();
  },
  methods: {
    // @exposed-api
    reset: function reset() {
      this.currentDate = this.getInitialDate();
      this.scrollIntoView();
    },
    init: function init() {
      const _this = this;

      if (this.poppable && !this.value) {
        return;
      }

      this.$nextTick(() => {
        // add Math.floor to avoid decimal height issues
        // https://github.com/youzan/vant/issues/5640
        _this.bodyHeight = Math.floor(_this.$refs.body.getBoundingClientRect().height);

        _this.onScroll();
      });
      this.scrollIntoView();
    },
    // scroll to current month
    scrollIntoView: function scrollIntoView() {
      const _this2 = this;

      this.$nextTick(() => {
        const { currentDate } = _this2;
        const targetDate = _this2.type === 'single' ? currentDate : currentDate[0];
        const displayed = _this2.value || !_this2.poppable;
        /* istanbul ignore if */

        if (!targetDate || !displayed) {
          return;
        }

        _this2.months.some((month, index) => {
          if ((0, _utils.compareMonth)(month, targetDate) === 0) {
            _this2.$refs.months[index].scrollIntoView();

            return true;
          }

          return false;
        });
      });
    },
    getInitialDate: function getInitialDate() {
      const { type } = this;
      const { minDate } = this;
      const { maxDate } = this;
      const { defaultDate } = this;
      let defaultVal = new Date();

      if ((0, _utils.compareDay)(defaultVal, minDate) === -1) {
        defaultVal = minDate;
      } else if ((0, _utils.compareDay)(defaultVal, maxDate) === 1) {
        defaultVal = maxDate;
      }

      if (type === 'range') {
        const _ref = defaultDate || [];
        const startDay = _ref[0];
        const endDay = _ref[1];

        return [startDay || defaultVal, endDay || (0, _utils.getNextDay)(defaultVal)];
      }

      if (type === 'multiple') {
        return defaultDate || [defaultVal];
      }

      return defaultDate || defaultVal;
    },
    // calculate the position of the elements
    // and find the elements that needs to be rendered
    onScroll: function onScroll() {
      const _this$$refs = this.$refs;
      const { body } = _this$$refs;
      const { months } = _this$$refs;
      const top = (0, _scroll.getScrollTop)(body);
      const bottom = top + this.bodyHeight;
      const heights = months.map((item) => item.height);
      const heightSum = heights.reduce((a, b) => a + b, 0); // iOS scroll bounce may exceed the range

      /* istanbul ignore next */

      if (top < 0 || bottom > heightSum && top > 0) {
        return;
      }

      let height = 0;
      let currentMonth;

      for (let i = 0; i < months.length; i++) {
        const visible = height <= bottom && height + heights[i] >= top;

        if (visible && !currentMonth) {
          currentMonth = months[i];
        }

        months[i].visible = visible;
        height += heights[i];
      }
      /* istanbul ignore else */


      if (currentMonth) {
        this.subtitle = currentMonth.title;
      }
    },
    onClickDay: function onClickDay(item) {
      const { date } = item;
      const { type } = this;
      const { currentDate } = this;

      if (type === 'range') {
        const startDay = currentDate[0];
        const endDay = currentDate[1];

        if (startDay && !endDay) {
          const compareToStart = (0, _utils.compareDay)(date, startDay);

          if (compareToStart === 1) {
            this.select([startDay, date], true);
          } else if (compareToStart === -1) {
            this.select([date, null]);
          } else if (this.allowSameDay) {
            this.select([date, date]);
          }
        } else {
          this.select([date, null]);
        }
      } else if (type === 'multiple') {
        let selectedIndex;
        const selected = this.currentDate.some((dateItem, index) => {
          const equal = (0, _utils.compareDay)(dateItem, date) === 0;

          if (equal) {
            selectedIndex = index;
          }

          return equal;
        });

        if (selected) {
          currentDate.splice(selectedIndex, 1);
        } else {
          this.select([].concat(currentDate, [date]));
        }
      } else {
        this.select(date, true);
      }
    },
    togglePopup: function togglePopup(val) {
      this.$emit('input', val);
    },
    select: function select(date, complete) {
      const _this3 = this;

      const emit = function emit(date) {
        _this3.currentDate = date;

        _this3.$emit('select', (0, _utils.copyDates)(_this3.currentDate));
      };

      if (complete && this.type === 'range') {
        const valid = this.checkRange(date);

        if (!valid) {
          // auto selected to max range if showConfirm
          if (this.showConfirm) {
            emit([date[0], (0, _utils.getDayByOffset)(date[0], this.maxRange - 1)]);
          } else {
            emit(date);
          }

          return;
        }
      }

      emit(date);

      if (complete && !this.showConfirm) {
        this.onConfirm();
      }
    },
    checkRange: function checkRange(date) {
      const { maxRange } = this;
      const { rangePrompt } = this;

      if (maxRange && (0, _utils.calcDateNum)(date) > maxRange) {
        (0, _toast.default)(rangePrompt || (0, _utils.t)('rangePrompt', maxRange));
        return false;
      }

      return true;
    },
    onConfirm: function onConfirm() {
      this.$emit('confirm', (0, _utils.copyDates)(this.currentDate));
    },
    genMonth: function genMonth(date, index) {
      const h = this.$createElement;
      const showMonthTitle = index !== 0 || !this.showSubtitle;
      return h(_Month.default, {
        ref: 'months',
        refInFor: true,
        attrs: {
          date,
          type: this.type,
          color: this.color,
          minDate: this.minDate,
          maxDate: this.maxDate,
          showMark: this.showMark,
          formatter: this.formatter,
          rowHeight: this.rowHeight,
          currentDate: this.currentDate,
          showSubtitle: this.showSubtitle,
          allowSameDay: this.allowSameDay,
          showMonthTitle,
        },
        on: {
          click: this.onClickDay,
        },
      });
    },
    genFooterContent: function genFooterContent() {
      const h = this.$createElement;
      const slot = this.slots('footer');

      if (slot) {
        return slot;
      }

      if (this.showConfirm) {
        const text = this.buttonDisabled ? this.confirmDisabledText : this.confirmText;
        return h(_button.default, {
          attrs: {
            round: true,
            block: true,
            type: 'danger',
            color: this.color,
            disabled: this.buttonDisabled,
            nativeType: 'button',
          },
          class: (0, _utils.bem)('confirm'),
          on: {
            click: this.onConfirm,
          },
        }, [text || (0, _utils.t)('confirm')]);
      }
    },
    genFooter: function genFooter() {
      const h = this.$createElement;
      return h('div', {
        class: (0, _utils.bem)('footer', {
          unfit: !this.safeAreaInsetBottom,
        }),
      }, [this.genFooterContent()]);
    },
    genCalendar: function genCalendar() {
      const _this4 = this;

      const h = this.$createElement;
      return h('div', {
        class: (0, _utils.bem)(),
      }, [h(_Header.default, {
        attrs: {
          title: this.title,
          showTitle: this.showTitle,
          subtitle: this.subtitle,
          showSubtitle: this.showSubtitle,
        },
        scopedSlots: {
          title: function title() {
            return _this4.slots('title');
          },
        },
      }), h('div', {
        ref: 'body',
        class: (0, _utils.bem)('body'),
        on: {
          scroll: this.onScroll,
        },
      }, [this.months.map(this.genMonth)]), this.genFooter()]);
    },
  },
  render: function render() {
    const _this5 = this;

    const h = arguments[0];

    if (this.poppable) {
      let _attrs;

      const createListener = function createListener(name) {
        return function () {
          return _this5.$emit(name);
        };
      };

      return h(_popup.default, {
        attrs: (_attrs = {
          round: true,
          value: this.value,
        }, _attrs.round = this.round, _attrs.position = this.position, _attrs.closeable = this.showTitle || this.showSubtitle, _attrs.getContainer = this.getContainer, _attrs.closeOnPopstate = this.closeOnPopstate, _attrs.closeOnClickOverlay = this.closeOnClickOverlay, _attrs),
        class: (0, _utils.bem)('popup'),
        on: {
          input: this.togglePopup,
          open: createListener('open'),
          opened: createListener('opened'),
          close: createListener('close'),
          closed: createListener('closed'),
        },
      }, [this.genCalendar()]);
    }

    return this.genCalendar();
  },
});

exports.default = _default2;
